﻿using Infrastructure;
using Infrastructure.Attribute;
using ZR.Infrastructure.Cache;
using ZR.Model;
using ZR.Service;
using ZR.ServiceCore.Model;
using ZR.ServiceCore.Model.Dto;
using ZR.ServiceCore.Services.IService;

namespace ZR.ServiceCore.Services;
[AppService(ServiceType = typeof(ISysFieldService), ServiceLifetime = LifeTime.Transient)]
public class SysFieldService : BaseService<SysField>, ISysFieldService
{
    private readonly ISysRoleFieldService _sysRoleFieldService;

    public SysFieldService(ISysRoleFieldService sysRoleFieldService)
    {
        _sysRoleFieldService = sysRoleFieldService;
    }

    public async Task<PagedInfo<SysModelDto>> GetModelList(PagerInfo pagerInfo)
    {
        if (!await RedisServer.Cache.ExistsAsync("ModelList")) throw new CustomException("请先初始化，再配置");
        var list = (await RedisServer.Cache.GetAsync<List<SysModelDto>>("ModelList")).ToList();
        var skipCount = (pagerInfo.PageNum - 1) * pagerInfo.PageSize;
        return new PagedInfo<SysModelDto>
        {
            PageSize = pagerInfo.PageSize,
            PageIndex = pagerInfo.PageNum,
            Result = list.Skip(skipCount).Take(pagerInfo.PageSize).ToList(),
            TotalNum = list.Count
        };
    }

    public async Task<List<SysFieldDto>> GetFields(string fullName, long roleId)
    {
        var fields = await Queryable()
            .Where(it => it.FullName == fullName)
            .WithCache(10 * 60)
            .ToListAsync();
        var roleFields = await _sysRoleFieldService
            .Queryable()
            .Where(it => it.RoleId == roleId)
            .Select(it => it.FieldId)
            .WithCache()
            .ToListAsync();
        var list = fields.Select(it => new SysFieldDto
        {
            FieldName = it.FieldName,
            FieldType = it.FieldType,
            FullName = it.FullName,
            Id = it.Id,
            // IsClass = it.IsClass,
            IsPermission = !roleFields.Contains(it.Id)
        }).ToList();
        return list;
    }

    public async Task<bool> InitFields()
    {
        var serviceCoreModels = AppDomain.CurrentDomain
            .GetAssemblies()
            .First(it => it.FullName != null && it.FullName.Contains("ZR.ServiceCore"))
            .ExportedTypes
            .Where(p => p.FullName != null && p.FullName.StartsWith("ZR.ServiceCore.Model"))
            .Select(it => new
            {
                it.FullName,
                Properties = it.GetProperties().Select(pt => new
                {
                    FieldName = pt.Name,
                    FieldType = pt.PropertyType.FullName,
                    // IsClass = pt.PropertyType.IsClass,
                    // IsArray = pt.PropertyType.IsArray,
                    // IsList = pt.PropertyType.IsClass ? pt.DeclaringType.FullName : string.Empty
                }).ToList()
                // Properties = it.GetProperties()
            })
            .ToList();
        var modelList = serviceCoreModels.Select(it => new SysModelDto{ FullName = it.FullName }).ToList();
        if (!await RedisServer.Cache.SetAsync("ModelList", modelList)) 
            throw new CustomException("插入缓存失败，请联系管理员");
        
        foreach (var serviceCoreModel in serviceCoreModels)
        {
            var sysFields = serviceCoreModel.Properties
                .Select(property => new SysField
                {
                    FieldName = property.FieldName, 
                    FullName = serviceCoreModel.FullName, 
                    FieldType = property.FieldType, 
                    // IsClass = property.IsClass ? "1" : "0"
                }).ToList();
            await Deleteable()
                .Where(it =>
                    !sysFields.Select(sf => sf.FieldName)
                        .ToArray().Contains(it.FieldName))
                .Where(it => it.FullName == serviceCoreModel.FullName)
                .ExecuteCommandAsync();
            var sysFieldStore = await Storageable(sysFields)
                .WhereColumns(it => new { it.FieldName, it.FullName })
                .ToStorageAsync();
            await sysFieldStore
                .AsInsertable
                .ExecuteReturnSnowflakeIdListAsync();
            await sysFieldStore
                .AsUpdateable
                .IgnoreColumns(it => it.Id)
                .ExecuteCommandAsync();
        }

        return true;
    }
}

